00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038
00039 #include "Array.h"
00040 #include "util.h"
00041 #include "debug.h"
00042 #include "InternalErr.h"
00043 #include "escaping.h"
00044
00045 #include <algorithm>
00046 #include <functional>
00047
00048 using namespace std;
00049
00050 namespace libdap {
00051
00052 void
00053 Array::_duplicate(const Array &a)
00054 {
00055 _shape = a._shape;
00056 }
00057
00058
00059
00060
00061
00062
00063
00071 void
00072 Array::update_length(int)
00073 {
00074 int length = 1;
00075 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00076 length *= (*i).c_size > 0 ? (*i).c_size : 1;
00077 }
00078
00079 set_length(length);
00080 }
00081
00082
00083
00084
00100 Array::Array(const string &n, BaseType *v) : Vector(n, 0, dods_array_c)
00101 {
00102 add_var(v);
00103 }
00104
00118 Array::Array(const string &n, const string &d, BaseType *v)
00119 : Vector(n, d, 0, dods_array_c)
00120 {
00121 add_var(v);
00122 }
00123
00125 Array::Array(const Array &rhs) : Vector(rhs)
00126 {
00127 _duplicate(rhs);
00128 }
00129
00131 Array::~Array()
00132 {
00133 DBG(cerr << "Entering ~Array (" << this << ")" << endl);
00134 DBG(cerr << "Exiting ~Array" << endl);
00135 }
00136
00137 BaseType *
00138 Array::ptr_duplicate()
00139 {
00140 return new Array(*this);
00141 }
00142
00143 Array &
00144 Array::operator=(const Array &rhs)
00145 {
00146 if (this == &rhs)
00147 return *this;
00148
00149 dynamic_cast<Vector &>(*this) = rhs;
00150
00151 _duplicate(rhs);
00152
00153 return *this;
00154 }
00155
00175 void
00176 Array::add_var(BaseType *v, Part)
00177 {
00178 if (v && v->type() == dods_array_c) {
00179 Array &a = dynamic_cast<Array&>(*v);
00180 Vector::add_var(a.var());
00181 Dim_iter i = a.dim_begin();
00182 Dim_iter i_end = a.dim_end();
00183 while (i != i_end) {
00184 append_dim(a.dimension_size(i), a.dimension_name(i));
00185 ++i;
00186 }
00187 }
00188 else {
00189 Vector::add_var(v);
00190 }
00191 }
00192
00204 void
00205 Array::append_dim(int size, string name)
00206 {
00207 dimension d;
00208
00209
00210 d.size = size;
00211 d.name = www2id(name);
00212
00213
00214 d.start = 0;
00215 d.stop = size - 1;
00216 d.stride = 1;
00217 d.c_size = size;
00218
00219 _shape.push_back(d);
00220
00221 update_length(size);
00222 }
00223
00229 void
00230 Array::prepend_dim(int size, const string& name)
00231 {
00232 dimension d;
00233
00234
00235 d.size = size;
00236 d.name = www2id(name);
00237
00238
00239 d.start = 0;
00240 d.stop = size - 1;
00241 d.stride = 1;
00242 d.c_size = size;
00243
00244
00245 _shape.insert(_shape.begin(), d);
00246
00247 update_length(size);
00248 }
00249
00256 void
00257 Array::reset_constraint()
00258 {
00259 set_length(-1);
00260
00261 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00262 (*i).start = 0;
00263 (*i).stop = (*i).size - 1;
00264 (*i).stride = 1;
00265 (*i).c_size = (*i).size;
00266
00267 update_length((*i).size);
00268 }
00269 }
00270
00271
00281 void
00282 Array::clear_constraint()
00283 {
00284 reset_constraint();
00285 }
00286
00287
00288
00289 static const char *array_sss = \
00290 "Invalid constraint parameters: At least one of the start, stride or stop \n\
00291 specified do not match the array variable.";
00292
00312 void
00313 Array::add_constraint(Dim_iter i, int start, int stride, int stop)
00314 {
00315 dimension &d = *i ;
00316
00317
00318
00319
00320
00321 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
00322 throw Error(malformed_expr, array_sss);
00323
00324 if (((stop - start) / stride + 1) > d.size)
00325 throw Error(malformed_expr, array_sss);
00326
00327 d.start = start;
00328 d.stop = stop;
00329 d.stride = stride;
00330
00331 d.c_size = (stop - start) / stride + 1;
00332
00333 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
00334
00335 update_length(d.c_size);
00336 }
00337
00339 Array::Dim_iter
00340 Array::dim_begin()
00341 {
00342 return _shape.begin() ;
00343 }
00344
00346 Array::Dim_iter
00347 Array::dim_end()
00348 {
00349 return _shape.end() ;
00350 }
00351
00361 unsigned int
00362 Array::dimensions(bool )
00363 {
00364 unsigned int dim = 0;
00365 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00366 dim++;
00367 }
00368
00369 return dim;
00370 }
00371
00389 int
00390 Array::dimension_size(Dim_iter i, bool constrained)
00391 {
00392 int size = 0;
00393
00394 if (!_shape.empty()) {
00395 if (constrained)
00396 size = (*i).c_size;
00397 else
00398 size = (*i).size;
00399 }
00400
00401 return size;
00402 }
00403
00422 int
00423 Array::dimension_start(Dim_iter i, bool )
00424 {
00425 return (!_shape.empty()) ? (*i).start : 0;
00426 }
00427
00446 int
00447 Array::dimension_stop(Dim_iter i, bool )
00448 {
00449 return (!_shape.empty()) ? (*i).stop : 0;
00450 }
00451
00471 int
00472 Array::dimension_stride(Dim_iter i, bool )
00473 {
00474 return (!_shape.empty()) ? (*i).stride : 0;
00475 }
00476
00487 string
00488 Array::dimension_name(Dim_iter i)
00489 {
00490
00491
00492
00493
00494
00495 if (_shape.empty())
00496 throw InternalErr(__FILE__, __LINE__,
00497 "*This* array has no dimensions.");
00498 return (*i).name;
00499 }
00500
00501 #if FILE_METHODS
00502
00519 void
00520 Array::print_decl(FILE *out, string space, bool print_semi,
00521 bool constraint_info, bool constrained)
00522 {
00523 if (constrained && !send_p())
00524 return;
00525
00526
00527 var()->print_decl(out, space, false, constraint_info, constrained);
00528
00529 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00530 fprintf(out, "[") ;
00531 if ((*i).name != "") {
00532 fprintf(out, "%s = ", id2www((*i).name).c_str()) ;
00533 }
00534 if (constrained) {
00535 fprintf(out, "%d]", (*i).c_size) ;
00536 }
00537 else {
00538 fprintf(out, "%d]", (*i).size) ;
00539 }
00540 }
00541
00542 if (print_semi) {
00543 fprintf(out, ";\n") ;
00544 }
00545 }
00546 #endif
00547
00565 void
00566 Array::print_decl(ostream &out, string space, bool print_semi,
00567 bool constraint_info, bool constrained)
00568 {
00569 if (constrained && !send_p())
00570 return;
00571
00572
00573 var()->print_decl(out, space, false, constraint_info, constrained);
00574
00575 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00576 out << "[" ;
00577 if ((*i).name != "") {
00578 out << id2www((*i).name) << " = " ;
00579 }
00580 if (constrained) {
00581 out << (*i).c_size << "]" ;
00582 }
00583 else {
00584 out << (*i).size << "]" ;
00585 }
00586 }
00587
00588 if (print_semi) {
00589 out << ";\n" ;
00590 }
00591 }
00592 #if FILE_METHODS
00593 void
00594 Array::print_xml(FILE *out, string space, bool constrained)
00595 {
00596 print_xml_core(out, space, constrained, "Array");
00597 }
00598 #endif
00599 void
00600 Array::print_xml(ostream &out, string space, bool constrained)
00601 {
00602 print_xml_core(out, space, constrained, "Array");
00603 }
00604 #if FILE_METHODS
00605 void
00606 Array::print_as_map_xml(FILE *out, string space, bool constrained)
00607 {
00608 print_xml_core(out, space, constrained, "Map");
00609 }
00610 #endif
00611 void
00612 Array::print_as_map_xml(ostream &out, string space, bool constrained)
00613 {
00614 print_xml_core(out, space, constrained, "Map");
00615 }
00616 #if FILE_METHODS
00617 class PrintArrayDim : public unary_function<Array::dimension&, void>
00618 {
00619 FILE *d_out;
00620 string d_space;
00621 bool d_constrained;
00622 public:
00623 PrintArrayDim(FILE *o, string s, bool c)
00624 : d_out(o), d_space(s), d_constrained(c)
00625 {}
00626
00627 void operator()(Array::dimension &d)
00628 {
00629 int size = d_constrained ? d.c_size : d.size;
00630 if (d.name.empty())
00631 fprintf(d_out, "%s<dimension size=\"%d\"/>\n", d_space.c_str(),
00632 size);
00633 else
00634 fprintf(d_out, "%s<dimension name=\"%s\" size=\"%d\"/>\n",
00635 d_space.c_str(), id2xml(d.name).c_str(), size);
00636 }
00637 };
00638
00639 void
00640 Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
00641 {
00642 if (constrained && !send_p())
00643 return;
00644
00645 fprintf(out, "%s<%s", space.c_str(), tag.c_str());
00646 if (!name().empty())
00647 fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00648 fprintf(out , ">\n");
00649
00650 get_attr_table().print_xml(out, space + " ", constrained);
00651
00652 BaseType *btp = var();
00653 string tmp_name = btp->name();
00654 btp->set_name("");
00655 btp->print_xml(out, space + " ", constrained);
00656 btp->set_name(tmp_name);
00657
00658 for_each(dim_begin(), dim_end(),
00659 PrintArrayDim(out, space + " ", constrained));
00660
00661 fprintf(out, "%s</%s>\n", space.c_str(), tag.c_str());
00662 }
00663 #endif
00664
00665 class PrintArrayDimStrm : public unary_function<Array::dimension&, void>
00666 {
00667 ostream &d_out;
00668 string d_space;
00669 bool d_constrained;
00670 public:
00671 PrintArrayDimStrm(ostream &o, string s, bool c)
00672 : d_out(o), d_space(s), d_constrained(c)
00673 {}
00674
00675 void operator()(Array::dimension &d)
00676 {
00677 int size = d_constrained ? d.c_size : d.size;
00678 if (d.name.empty())
00679 d_out << d_space << "<dimension size=\"" << size << "\"/>\n" ;
00680 else
00681 d_out << d_space << "<dimension name=\"" << id2xml(d.name)
00682 << "\" size=\"" << size << "\"/>\n" ;
00683 }
00684 };
00685
00686 void
00687 Array::print_xml_core(ostream &out, string space, bool constrained, string tag)
00688 {
00689 if (constrained && !send_p())
00690 return;
00691
00692 out << space << "<" << tag ;
00693 if (!name().empty())
00694 out << " name=\"" << id2xml(name()) << "\"" ;
00695 out << ">\n" ;
00696
00697 get_attr_table().print_xml(out, space + " ", constrained);
00698
00699 BaseType *btp = var();
00700 string tmp_name = btp->name();
00701 btp->set_name("");
00702 btp->print_xml(out, space + " ", constrained);
00703 btp->set_name(tmp_name);
00704
00705 for_each(dim_begin(), dim_end(),
00706 PrintArrayDimStrm(out, space + " ", constrained));
00707
00708 out << space << "</" << tag << ">\n" ;
00709 }
00710
00711 #if FILE_METHODS
00712
00722 unsigned int
00723 Array::print_array(FILE *out, unsigned int index, unsigned int dims,
00724 unsigned int shape[])
00725 {
00726 if (dims == 1) {
00727 fprintf(out, "{") ;
00728 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00729 var(index++)->print_val(out, "", false);
00730 fprintf(out, ", ") ;
00731 }
00732 var(index++)->print_val(out, "", false);
00733 fprintf(out, "}") ;
00734
00735 return index;
00736 }
00737 else {
00738 fprintf(out, "{") ;
00739
00740
00741
00742
00743
00744
00745 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00746 index = print_array(out, index, dims - 1, shape + 1);
00747 fprintf(out, ",") ;
00748 }
00749 index = print_array(out, index, dims - 1, shape + 1);
00750 fprintf(out, "}") ;
00751
00752 return index;
00753 }
00754 }
00755 #endif
00756
00767 unsigned int
00768 Array::print_array(ostream &out, unsigned int index, unsigned int dims,
00769 unsigned int shape[])
00770 {
00771 if (dims == 1) {
00772 out << "{" ;
00773 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00774 var(index++)->print_val(out, "", false);
00775 out << ", " ;
00776 }
00777 var(index++)->print_val(out, "", false);
00778 out << "}" ;
00779
00780 return index;
00781 }
00782 else {
00783 out << "{" ;
00784
00785
00786
00787
00788
00789
00790 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00791 index = print_array(out, index, dims - 1, shape + 1);
00792 out << "," ;
00793 }
00794 index = print_array(out, index, dims - 1, shape + 1);
00795 out << "}" ;
00796
00797 return index;
00798 }
00799 }
00800
00801 #if FILE_METHODS
00802 void
00803 Array::print_val(FILE *out, string space, bool print_decl_p)
00804 {
00805
00806
00807
00808
00809
00810
00811 if (print_decl_p) {
00812 print_decl(out, space, false, false, false);
00813 fprintf(out, " = ") ;
00814 }
00815
00816 unsigned int *shape = new unsigned int[_shape.size()];
00817 unsigned int index = 0;
00818 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < _shape.size(); i++)
00819 shape[index++] = dimension_size(i, true);
00820
00821 print_array(out, 0, _shape.size(), shape);
00822
00823 delete [] shape; shape = 0;
00824
00825 if (print_decl_p) {
00826 fprintf(out, ";\n") ;
00827 }
00828 }
00829 #endif
00830
00831 void
00832 Array::print_val(ostream &out, string space, bool print_decl_p)
00833 {
00834
00835
00836
00837
00838
00839
00840 if (print_decl_p) {
00841 print_decl(out, space, false, false, false);
00842 out << " = " ;
00843 }
00844
00845 unsigned int *shape = new unsigned int[dimensions(true)];
00846 unsigned int index = 0;
00847 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
00848 shape[index++] = dimension_size(i, true);
00849
00850 print_array(out, 0, dimensions(true), shape);
00851
00852 delete [] shape; shape = 0;
00853
00854 if (print_decl_p) {
00855 out << ";\n" ;
00856 }
00857 }
00858
00868 bool
00869 Array::check_semantics(string &msg, bool)
00870 {
00871 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
00872
00873 if (!sem)
00874 msg = "An array variable must have dimensions";
00875
00876 return sem;
00877 }
00878
00887 void
00888 Array::dump(ostream &strm) const
00889 {
00890 strm << DapIndent::LMarg << "Array::dump - ("
00891 << (void *)this << ")" << endl ;
00892 DapIndent::Indent() ;
00893 Vector::dump(strm) ;
00894 strm << DapIndent::LMarg << "shape:" << endl ;
00895 DapIndent::Indent() ;
00896 Dim_citer i = _shape.begin() ;
00897 Dim_citer ie = _shape.end() ;
00898 unsigned int dim_num = 0 ;
00899 for (; i != ie; i++) {
00900 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":"
00901 << endl ;
00902 DapIndent::Indent() ;
00903 strm << DapIndent::LMarg << "name: " << (*i).name << endl ;
00904 strm << DapIndent::LMarg << "size: " << (*i).size << endl ;
00905 strm << DapIndent::LMarg << "start: " << (*i).start << endl ;
00906 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl ;
00907 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl ;
00908 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size
00909 << endl ;
00910 DapIndent::UnIndent() ;
00911 }
00912 DapIndent::UnIndent() ;
00913 DapIndent::UnIndent() ;
00914 }
00915
00916 }
00917